package com.yizisu.basemvvm.mvvm

import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.graphics.Point
import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.PopupWindow
import androidx.appcompat.app.AppCompatActivity
import com.yizisu.basemvvm.R
import com.yizisu.basemvvm.utils.dip
import com.yizisu.basemvvm.utils.safeGet
import com.yizisu.basemvvm.utils.setWindowAlpha


/**
 * 若红楼梦空，亦初心不变
 * 作者：thinker
 * 包名：com.yizisu.basemvvm.mvvm
 * 时间：2019/5/30 12:38
 * 描述：直接new出来的PopupWindom
 * 子类实现的话，请继承{@see BasePopupWindow}
 */
open class MvvmPopupWindow : PopupWindow {
    private var mContext: Context? = null
    val context: Context?
        get() {
            val ctx = mContext
            return if (ctx is ContextWrapper) {
                ctx.baseContext
            } else {
                ctx
            }
        }
    //创建的时候赋值，取消的时候恢复
    private var oldWindowAlpha = 1f
    var defaultWindowAlphaWhenPopup = 0.6f


    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : this(
            context,
            attrs,
            defStyleAttr,
            0
    )

    constructor(
            context: Context?,
            attrs: AttributeSet?,
            defStyleAttr: Int,
            defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes) {
        initPopupWindow(context)
    }

    constructor() : this(
            width = ViewGroup.LayoutParams.MATCH_PARENT,
            height = ViewGroup.LayoutParams.WRAP_CONTENT
    )

    constructor(contentView: View?) : this(
            contentView = contentView,
            width = ViewGroup.LayoutParams.MATCH_PARENT,
            height = ViewGroup.LayoutParams.WRAP_CONTENT
    )

    constructor(width: Int, height: Int) : this(null, width, height)
    constructor(contentView: View?, width: Int, height: Int) : this(
            contentView,
            width,
            height,
            true
    )

    constructor(
            contentView: View?,
            width: Int,
            height: Int,
            focusable: Boolean
    ) : super(contentView, width, height, focusable) {
        initPopupWindow(contentView?.context)
    }

    private fun initPopupWindow(context: Context?) {
        mContext = context
        //点击外面popupWindow消失
        isOutsideTouchable = true
        //popupWindow获取焦点
        isFocusable = true
        //popupWindow设置背景图
        setBackgroundDrawable(ColorDrawable())
    }

    override fun dismiss() {
        setWindowBackgroundAlpha(oldWindowAlpha)
        super.dismiss()
    }


    override fun showAsDropDown(anchor: View?) {
        showAsDropDown(anchor, 0, 0)
    }

    override fun showAsDropDown(anchor: View?, xoff: Int, yoff: Int) {
        showAsDropDown(anchor, xoff, yoff, Gravity.TOP or Gravity.START)
    }

    override fun showAsDropDown(anchor: View?, xoff: Int, yoff: Int, gravity: Int) {
        showPopupWindow(R.style.PopupWindowScaleStartTopIn)
        super.showAsDropDown(anchor, xoff, yoff, gravity)
    }

    override fun showAtLocation(parent: View?, gravity: Int, x: Int, y: Int) {
        when (gravity) {
            Gravity.BOTTOM -> {
                showPopupWindow(R.style.PopupWindowBottomIn)
            }
            Gravity.TOP -> {
                showPopupWindow(R.style.PopupWindowTopIn)
            }
            else -> {
                showPopupWindow(0)
            }
        }
        super.showAtLocation(parent, gravity, x, y)
    }

    /**
     * 显示在按钮的上方或者下方
     *  isGravityEnd : true ,弹窗与view的右边缘对齐，可以通过设置xoff来横向偏移
     *  isGravityEnd : false ,弹窗与view的左边缘对齐，可以通过设置xoff来横向偏移
     */
    fun showAsDropTopOrBottom(anchor: View, isGravityEnd: Boolean, xoff: Int = 0, yoff: Int = 0) {
        val touch = intArrayOf(0, 0)
        val screenPoint = Point()
        anchor.display.getRealSize(screenPoint)
        anchor.getLocationOnScreen(touch)
        val isShowBottom = touch[1] < screenPoint.y / 2
        if (isShowBottom) {
            if (isGravityEnd) {
                animationStyle = R.style.PopupWindowScaleEndTopIn
                showAtLocation(
                        anchor,
                        Gravity.TOP or Gravity.END,
                        screenPoint.x - touch[0] - anchor.width + xoff,
                        touch[1] + anchor.height + yoff
                )
            } else {
                animationStyle = R.style.PopupWindowScaleStartTopIn
                showAtLocation(
                        anchor,
                        Gravity.TOP or Gravity.START,
                        touch[0] + xoff,
                        touch[1] + anchor.height + yoff
                )
            }
        } else {
            if (isGravityEnd) {
                animationStyle = R.style.PopupWindowScaleEndTopInToTop
                showAtLocation(
                        anchor,
                        Gravity.BOTTOM or Gravity.END,
                        screenPoint.x - touch[0] - anchor.width + xoff,
                        screenPoint.y - touch[1] + yoff
                )
            } else {
                animationStyle = R.style.PopupWindowScaleStartTopInToTop
                showAtLocation(
                        anchor,
                        Gravity.BOTTOM or Gravity.START,
                        touch[0] + xoff,
                        screenPoint.y - touch[1] + yoff
                )
            }
        }
    }


    /**
     * 显示在屏幕下方
     */
    fun showAtBottom() {
        showPopupWindow(R.style.PopupWindowBottomIn)
        super.showAtLocation(contentView, Gravity.BOTTOM, 0, 0)
    }

    /**
     * 显示在屏幕上方
     */
    fun showAtTop() {
        showPopupWindow(R.style.PopupWindowTopIn)
        super.showAtLocation(contentView, Gravity.TOP, 0, 0)
    }

    /**
     * 显示popupWindow
     */
    private fun showPopupWindow(defaultAnimStyle: Int) {
        setWindowBackgroundAlpha(defaultWindowAlphaWhenPopup)
        if (animationStyle <= 0) {
            animationStyle = defaultAnimStyle
        }
    }

    /**
     * 设置背景是否变灰
     */
    private fun setWindowBackgroundAlpha(bgAlpha: Float) {
        if (mContext == null) {
            mContext = contentView?.context
        }
        context.safeGet<Activity>()?.run {
            oldWindowAlpha = window?.attributes?.alpha ?: 1f
            setWindowAlpha(bgAlpha)
        }
    }
}